package com.ibeeking.found.org.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.org.b.rest.service.IOrgPositionService;
import com.ibeeking.found.org.service.common.dos.DepartmentDO;
import com.ibeeking.found.org.service.common.dos.OrgJobDO;
import com.ibeeking.found.org.service.common.dos.OrgPositionDO;
import com.ibeeking.found.org.service.common.param.OrgPositionParam;
import com.ibeeking.found.org.service.common.query.OrgPositionQuery;
import com.ibeeking.found.org.service.common.vo.DepartmentTreeVO;
import com.ibeeking.found.org.service.common.vo.OrgPositionVO;
import com.ibeeking.found.org.service.mapper.DepartmentMapper;
import com.ibeeking.found.org.service.mapper.OrgJobMapper;
import com.ibeeking.found.org.service.mapper.OrgPositionMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.TreeFastUtils;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName OrgPositionServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-29 14:48
 **/
@Service
public class OrgPositionServiceImpl extends ServiceImpl<OrgPositionMapper, OrgPositionDO> implements IOrgPositionService {

    @Resource
    private OrgPositionMapper orgPositionMapper;

    @Resource
    private OrgJobMapper orgJobMapper;

    @Resource
    private DepartmentMapper departmentMapper;

    @Override
    public List<OrgPositionVO> list(OrgPositionQuery query) {
        List<OrgPositionVO> resultVOS = new ArrayList<>();
        List<OrgPositionDO> entityDOS = orgPositionMapper.selectList(new LambdaQueryWrapper<OrgPositionDO>()
                .eq(query.getId()!=null ,OrgPositionDO::getId, query.getId())
                .eq(query.getDepartmentId()!=null ,OrgPositionDO::getDepartmentId, query.getDepartmentId())
                .in(Collections3.isNotEmpty(query.getDepartmentIds()),OrgPositionDO::getDepartmentId,query.getDepartmentIds())
                .eq(query.getJobId()!=null ,OrgPositionDO::getJobId, query.getJobId())
                .eq(StringUtils.isNotEmpty(query.getCode()),OrgPositionDO::getCode, query.getCode())
                .like(StringUtils.isNotEmpty(query.getName()),OrgPositionDO::getName, query.getName())
                .eq(query.getPublishStatus()!=null , OrgPositionDO::getPublishStatus,query.getPublishStatus())
                .orderByAsc(OrgPositionDO::getSort));
        if(Collections3.isNotEmpty(entityDOS)){
            List<DepartmentDO> orgDepartmentDOList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
            Map<Long, String> orgDepartmentNameMaps = Collections3.isNotEmpty(orgDepartmentDOList)?orgDepartmentDOList.parallelStream().collect(Collectors.toMap(DepartmentDO::getId, DepartmentDO::getName, (o, n) -> o)):null;

            List<OrgJobDO> orgJobDOList = orgJobMapper.selectList(new LambdaQueryWrapper<OrgJobDO>().eq(OrgJobDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
            Map<Long, String> orgJobNameMaps = Collections3.isNotEmpty(orgJobDOList)?orgJobDOList.parallelStream().collect(Collectors.toMap(OrgJobDO::getId, OrgJobDO::getName, (o, n) -> o)):null;

            resultVOS = entityDOS.stream().map(s->{
                OrgPositionVO  entityVO = BeanUtil.convertBean(s, OrgPositionVO.class);
                String deptName = orgDepartmentNameMaps!=null?orgDepartmentNameMaps.get(s.getDepartmentId()):"";
                entityVO.setDepartmentName(deptName);
                entityVO.setDeptJoinPosName(deptName.concat("-").concat(s.getName()));
                entityVO.setJobName(orgJobNameMaps!=null?orgJobNameMaps.get(s.getJobId()):"");
                entityVO.setPublishStatusName(PublishStatusEnum.getName(s.getPublishStatus()));
                return entityVO;
            }).collect(Collectors.toList());
        }
        return resultVOS;
    }

    @Override
    public List<OrgPositionVO> listAllAndSub(OrgPositionQuery query) {
        if(query.getDepartmentId() != null){
            List<Long> departmentIds = getAllDepartmentIdsByPId(query.getDepartmentId());
            query.setDepartmentIds(departmentIds);
        }
        List<OrgPositionVO> resultVOS = new ArrayList<>();
        List<OrgPositionDO> entityDOS = orgPositionMapper.selectList(new LambdaQueryWrapper<OrgPositionDO>()
                .eq(query.getId()!=null ,OrgPositionDO::getId, query.getId())
                .in(Collections3.isNotEmpty(query.getDepartmentIds()),OrgPositionDO::getDepartmentId,query.getDepartmentIds())
                .eq(query.getJobId()!=null ,OrgPositionDO::getJobId, query.getJobId())
                .eq(StringUtils.isNotEmpty(query.getCode()),OrgPositionDO::getCode, query.getCode())
                .like(StringUtils.isNotEmpty(query.getName()),OrgPositionDO::getName, query.getName())
                .eq(query.getPublishStatus()!=null , OrgPositionDO::getPublishStatus,query.getPublishStatus())
                .orderByAsc(OrgPositionDO::getSort));
        if(Collections3.isNotEmpty(entityDOS)){
            List<DepartmentDO> orgDepartmentDOList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
            Map<Long, String> orgDepartmentNameMaps = Collections3.isNotEmpty(orgDepartmentDOList)?orgDepartmentDOList.parallelStream().collect(Collectors.toMap(DepartmentDO::getId, DepartmentDO::getName, (o, n) -> o)):null;

            List<OrgJobDO> orgJobDOList = orgJobMapper.selectList(new LambdaQueryWrapper<OrgJobDO>().eq(OrgJobDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
            Map<Long, String> orgJobNameMaps = Collections3.isNotEmpty(orgJobDOList)?orgJobDOList.parallelStream().collect(Collectors.toMap(OrgJobDO::getId, OrgJobDO::getName, (o, n) -> o)):null;

            resultVOS = entityDOS.stream().map(s->{
                OrgPositionVO  entityVO = BeanUtil.convertBean(s, OrgPositionVO.class);
                String deptName = orgDepartmentNameMaps!=null?orgDepartmentNameMaps.get(s.getDepartmentId()):"";
                entityVO.setDepartmentName(deptName);
                entityVO.setDeptJoinPosName(deptName.concat("-").concat(s.getName()));
                entityVO.setJobName(orgJobNameMaps!=null?orgJobNameMaps.get(s.getJobId()):"");
                entityVO.setPublishStatusName(PublishStatusEnum.getName(s.getPublishStatus()));
                return entityVO;
            }).collect(Collectors.toList());
        }
        return resultVOS;
    }

    @Override
    public List<OrgPositionVO> queryByDepartmentId(Long departmentId) {
        OrgPositionQuery query = new OrgPositionQuery();
        query.setDepartmentId(departmentId);
        query.setPublishStatus(PublishStatusEnum.ENABLE.getValue());
        return this.getBean().list(query);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(OrgPositionParam param) {
        this.checkUnique(param);
        OrgPositionDO entityDO = BeanUtil.convertBean(param, OrgPositionDO.class);
        entityDO.setId(IdGenerator.getId());
        return orgPositionMapper.insert(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(OrgPositionParam param) {
        this.checkUnique(param);
        OrgPositionDO entityDO = BeanUtil.convertBean(param, OrgPositionDO.class);

        return orgPositionMapper.updateById(entityDO) > 0;
    }

    @Override
    public OrgPositionVO view(Long id) {
        OrgPositionDO entityDO = orgPositionMapper.selectById(id);
        List<DepartmentDO> orgDepartmentDOList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
        Map<Long, String> orgDepartmentNameMaps = Collections3.isNotEmpty(orgDepartmentDOList)?orgDepartmentDOList.parallelStream().collect(Collectors.toMap(DepartmentDO::getId, DepartmentDO::getName, (o, n) -> o)):null;

        List<OrgJobDO> orgJobDOList = orgJobMapper.selectList(new LambdaQueryWrapper<OrgJobDO>().eq(OrgJobDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
        Map<Long, String> orgJobNameMaps = Collections3.isNotEmpty(orgJobDOList)?orgJobDOList.parallelStream().collect(Collectors.toMap(OrgJobDO::getId, OrgJobDO::getName, (o, n) -> o)):null;

        OrgPositionVO entityVO = BeanUtil.convertBeanByJson(entityDO, OrgPositionVO.class);
        entityVO.setDepartmentName(orgDepartmentNameMaps!=null?orgDepartmentNameMaps.get(entityDO.getDepartmentId()):"");
        entityVO.setJobName(orgJobNameMaps!=null?orgJobNameMaps.get(entityDO.getJobId()):"");
        entityVO.setPublishStatusName(PublishStatusEnum.getName(entityDO.getPublishStatus()));
        return entityVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        OrgPositionDO entityDO = orgPositionMapper.selectById(id);

        entityDO.setPublishStatus(status);

        return orgPositionMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        OrgPositionDO entityDO = orgPositionMapper.selectById(id);
        if (entityDO == null) {
            return true;
        }
        //删除会员偏好关系表数据
        return orgPositionMapper.deleteById(id) > 0;
    }

    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(OrgPositionParam param) {
        if (param == null) {
            throw new BusinessException("当前职位数据不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<OrgPositionDO> queryWrapper = new LambdaQueryWrapper<OrgPositionDO>()
                .ne(param.getId() != null, OrgPositionDO::getId, param.getId())
                .eq(OrgPositionDO::getName, param.getName());
        List<OrgPositionDO> dos = orgPositionMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的职位!");
        }
    }

    private List<Long> getAllDepartmentIdsByPId(Long parentId){
        List<Long> departmentIdS = new ArrayList<>();
        departmentIdS.add(parentId);
        List<DepartmentDO> allDepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<>(DepartmentDO.class).eq(DepartmentDO::getPublishStatus,PublishStatusEnum.ENABLE.getValue()));
        List<DepartmentTreeVO> allDepartmentTrees = JsonUtils.jsonToList(allDepartmentList, DepartmentTreeVO.class);
        List<Long> result = new ArrayList<>();
        TreeFastUtils.selectLongCidByPid(result, allDepartmentTrees, departmentIdS);
        result.addAll(departmentIdS);
        return result;
    }

    private OrgPositionServiceImpl getBean(){
        return SpringBeanUtil.getBean(this.getClass());
    }
}